CREATE OR REPLACE EDITIONABLE PACKAGE BODY "SCOTT"."PKG_MODEL_ETF" is

  /*-------------------- 海量地向表MDL_ETF_MACD_GOLD_CROSS中插入数据 ---------------------*/
  procedure CAL_MDL_ETF_MACD_GOLD_CROSS(p_validate_120_not_decreasing in number,
                                        p_validate_250_not_decreasing in number,
                                        p_default_begin_date          in varchar2,
                                        p_end_date                    in varchar2,
                                        p_type                        in number) as
    -- 表示ETF_CODE
    v_etf_code varchar2(100);
    -- 表示开始时间
    v_begin_date varchar2(100);
    -- 表示ETF_DATE
    v_etf_date date;
    -- 记录数量
    v_record_num number;
    -- 上一个120日均线
    v_last_ma120 number;
    -- 上一个250日均线
    v_last_ma250 number;
    -- 1表示120日和250日均线都单调递增，0表示120日和250日均线至少有一个是递减的
    v_120_250_increasing number;
    -- 表示两天记录中的第一天，用于判断MACD是否发生了金叉或死叉
    v_first_etf etf_transaction_data%rowtype;
    -- 表示两天记录中的第二天，用于判断MACD是否发生了金叉或死叉
    v_second_etf etf_transaction_data%rowtype;
    -- 作为临时变量，表示ETF_CODE,BUY_DATE,SELL_DATE,BUY_PRICE,SELL_PRICE,BUY_DIF,BUY_DEA,SELL_DIF,SELL_DEA
    v_temp_etf_code       varchar2(100);
    v_temp_etf_buy_date   date;
    v_temp_etf_sell_date  date;
    v_temp_etf_buy_price  number;
    v_temp_etf_sell_price number;
    v_temp_etf_buy_dif    number;
    v_temp_etf_buy_dea    number;
    v_temp_etf_sell_dif   number;
    v_temp_etf_sell_dea   number;
    -- 用来判断现在是否是dif>dea的阶段，从而可以判断死叉
    v_start_track_gold_cross_stage number;
    -- 用来表示金叉和死叉是否发现了
    v_gold_cross_found  number;
    v_death_cross_found number;
    -- 每只指数初始的accumulative_profit_loss值为100（表示百分之一百），之后代表上一次交易的累计盈亏百分比
    v_init_last_acc_profit_loss number;
    -- 表示字段PROFIT_LOSS的临时变量
    v_temp_profit_loss number;
    -- 用于获取所有的ETF_CODE
    cursor cur_all_etf_code is
      select distinct t.code_ from etf_transaction_data t;
    -- 用于根据ETF_CODE获取某一只指数的所有交易记录
    cursor cur_single_etf is
      select *
        from etf_transaction_data t
       where t.code_ = lower(v_etf_code)
         and t.date_ between to_date(v_begin_date, 'yyyy-mm-dd') and
             to_date(p_end_date, 'yyyy-mm-dd')
       order by t.date_ asc;
    -- 表示etf表的记录，用于判断120日均线是否单调递减
    cursor cur_120_etf is
      select *
        from (select *
                from etf_transaction_data t
               where t.ma120 is not null
                 and t.code_ = v_etf_code
                 and t.date_ < v_etf_date
               order by t.date_ desc)
       where rownum <= 40;
    -- 表示etf表的记录，用于判断250日均线是否单调递减
    cursor cur_250_etf is
      select *
        from (select *
                from etf_transaction_data t
               where t.ma250 is not null
                 and t.code_ = v_etf_code
                 and t.date_ < v_etf_date
               order by t.date_ desc)
       where rownum <= 40;
    -- 用于获取某一只etf两天的交易记录，用于判断MACD是否发生了金叉或死叉
    cursor cur_single_etf_two_record is
      select *
        from (select *
                from etf_transaction_data t
               where t.date_ >= v_etf_date
                 and t.code_ = lower(v_etf_code)
                 and t.date_ between to_date(v_begin_date, 'yyyy-mm-dd') and
                     to_date(p_end_date, 'yyyy-mm-dd')
               order by t.date_ asc)
       where rownum <= 2;
  begin
    for i in cur_all_etf_code loop
      v_etf_code                     := lower(i.code_);
      v_init_last_acc_profit_loss    := 100;
      v_start_track_gold_cross_stage := 0;
    
      -- 设置开始时间
      begin
        select to_char(max(t.sell_date) + 1, 'yyyy-mm-dd')
          into v_begin_date
          from mdl_etf_macd_gold_cross t
         where t.etf_code = v_etf_code
           and t.type_ = p_type;
      exception
        when no_data_found then
          dbms_output.put_line('v_etf_code为【' || v_etf_code || '】，
          在mdl_etf_macd_gold_cross表中没有记录');
          v_begin_date := p_default_begin_date;
      end;
      if v_begin_date is null then
        v_begin_date := p_default_begin_date;
      end if;
    
      for j in cur_single_etf loop
        v_etf_date           := j.date_;
        v_record_num         := null;
        v_last_ma120         := null;
        v_last_ma250         := null;
        v_120_250_increasing := 1;
      
        -- 判断120日均线是否单调递减
        if p_validate_120_not_decreasing = 1 then
          select count(*)
            into v_record_num
            from etf_transaction_data t
           where t.ma120 is not null
             and t.code_ = v_etf_code
             and t.date_ <= v_etf_date;
          if v_record_num < 40 then
            continue;
          end if;
          for y in cur_120_etf loop
            if v_last_ma120 is null then
              v_last_ma120 := y.ma120;
              continue;
            end if;
            if v_last_ma120 < y.ma120 then
              v_120_250_increasing := 0;
              exit;
            end if;
            v_last_ma120 := y.ma120;
          end loop;
        end if;
      
        -- 判断250日均线是否单调递减
        if p_validate_250_not_decreasing = 1 then
          select count(*)
            into v_record_num
            from etf_transaction_data t
           where t.ma250 is not null
             and t.code_ = v_etf_code
             and t.date_ <= v_etf_date;
          if v_record_num < 40 then
            continue;
          end if;
          for y in cur_250_etf loop
            if v_last_ma250 is null then
              v_last_ma250 := y.ma250;
              continue;
            end if;
            if v_last_ma250 < y.ma250 then
              v_120_250_increasing := 0;
              exit;
            end if;
            v_last_ma250 := y.ma250;
          end loop;
        end if;
      
        -- 如果120日和250日均线有一个是单调递增，则跳过。但是如果之前已经买入，则不跳过
        if p_validate_120_not_decreasing = 1 or
           p_validate_250_not_decreasing = 1 then
          if v_120_250_increasing = 0 and
             v_start_track_gold_cross_stage = 0 then
            continue;
          end if;
        end if;
      
        -- 如果最早的数据是dif>dea，那么接下来只有可能先出现死叉，所以要判断：j.dif<j.dea，也就是说如果第一段数据是dif>dea，则将其忽略
        -- 之后在确认了金叉后，需要确认死叉，所以引入了表示变量v_start_track_gold_cross_stage，当其为1时，表示接下来只可能出现死叉
        if j.dif < j.dea or
           (j.dif > j.dea and v_start_track_gold_cross_stage = 1) then
          -- 分别将两天的记录赋给相应的变量
          for x in cur_single_etf_two_record loop
            if cur_single_etf_two_record%rowcount = 1 then
              v_first_etf := x;
            elsif cur_single_etf_two_record%rowcount = 2 then
              v_second_etf := x;
            end if;
          end loop;
          -- 如果出现了金叉，给临时变量赋值
          if v_first_etf.dif < v_first_etf.dea and
             v_second_etf.dif > v_second_etf.dea and
             v_start_track_gold_cross_stage = 0 then
            v_temp_etf_code      := v_second_etf.code_;
            v_temp_etf_buy_date  := v_second_etf.date_;
            v_temp_etf_buy_price := v_second_etf.close_price;
            v_temp_etf_buy_dif   := v_second_etf.dif;
            v_temp_etf_buy_dea   := v_second_etf.dea;
            v_gold_cross_found   := 1;
            -- 当金叉发生后，只可能发生死叉，因此要将v_start_track_gold_cross_stage设置为1
            v_start_track_gold_cross_stage := 1;
          
            dbms_output.put_line('gold cross   ' || j.date_);
          end if;
          -- 如果出现了死叉，给临时变量赋值
          if v_first_etf.dif > v_first_etf.dea and
             v_second_etf.dif < v_second_etf.dea and
             v_start_track_gold_cross_stage = 1 then
            v_temp_etf_sell_date  := v_second_etf.date_;
            v_temp_etf_sell_price := v_second_etf.close_price;
            v_temp_etf_sell_dif   := v_second_etf.dif;
            v_temp_etf_sell_dea   := v_second_etf.dea;
            v_death_cross_found   := 1;
            -- 当死叉发生后，只可能发生金叉，因此要将v_start_track_gold_cross_stage设置为0
            v_start_track_gold_cross_stage := 0;
          
            dbms_output.put_line('death cross   ' || j.date_);
          end if;
          -- 插入数据。要求这只指数在开始时间和结束时间内没有停牌或除权的情况
          if v_gold_cross_found = 1 and v_death_cross_found = 1 and
             v_temp_etf_buy_date is not null and
             v_temp_etf_sell_date is not null and
             v_temp_etf_code is not null then
            v_temp_profit_loss          := round((v_temp_etf_sell_price -
                                                 v_temp_etf_buy_price) /
                                                 v_temp_etf_buy_price,
                                                 4) * 100;
            v_init_last_acc_profit_loss := v_init_last_acc_profit_loss *
                                           (1 + v_temp_profit_loss / 100);
          
            insert into MDL_ETF_MACD_GOLD_CROSS
              (buy_date,
               sell_date,
               buy_price,
               sell_price,
               profit_loss,
               etf_code,
               accumulative_profit_loss,
               buy_dif,
               buy_dea,
               sell_dif,
               sell_dea,
               type_)
            values
              (v_temp_etf_buy_date,
               v_temp_etf_sell_date,
               v_temp_etf_buy_price,
               v_temp_etf_sell_price,
               v_temp_profit_loss,
               v_temp_etf_code,
               v_init_last_acc_profit_loss,
               v_temp_etf_buy_dif,
               v_temp_etf_buy_dea,
               v_temp_etf_sell_dif,
               v_temp_etf_sell_dea,
               p_type);
          
            v_gold_cross_found  := 0;
            v_death_cross_found := 0;
          end if;
        end if;
      end loop;
    end loop;
    commit;
  end CAL_MDL_ETF_MACD_GOLD_CROSS;

  /*----------------------- 海量地向表MDL_ETF_C_P_MA5_G_C中插入数据 ------------------------*/
  procedure CAL_MDL_ETF_CLOSE_PRICE_MA5_GC(p_validate_120_not_decreasing in number,
                                           p_validate_250_not_decreasing in number,
                                           p_default_begin_date          in varchar2,
                                           p_end_date                    in varchar2,
                                           p_type                        in number) as
    -- 表示ETF_CODE
    v_etf_code varchar2(100);
    -- 表示开始时间
    v_begin_date varchar2(100);
    -- 表示ETF_DATE
    v_etf_date date;
    -- 记录数量
    v_record_num number;
    -- 上一个120日均线
    v_last_ma120 number;
    -- 上一个250日均线
    v_last_ma250 number;
    -- 1表示120日和250日均线都单调递增，0表示120日和250日均线至少有一个是递减的
    v_120_250_increasing number;
    -- 作为临时变量，表示ETF_CODE,BUY_DATE,SELL_DATE,BUY_PRICE,SELL_PRICE,BUY_MA5,SELL_MA5
    v_temp_etf_code       varchar2(100);
    v_temp_etf_buy_date   date;
    v_temp_etf_sell_date  date;
    v_temp_etf_buy_price  number;
    v_temp_etf_sell_price number;
    v_temp_etf_buy_ma5    number;
    v_temp_etf_sell_ma5   number;
    -- 1表示close_price>ma5的阶段，2表示close_price<=ma5的阶段
    v_start_track_gold_cross_stage number;
    -- 每只指数初始的accumulative_profit_loss值为100（表示百分之一百），之后代表上一次交易的累计盈亏百分比
    v_init_last_acc_profit_loss number;
    -- 表示字段PROFIT_LOSS的临时变量
    v_temp_profit_loss number;
    -- 用于获取所有的ETF_CODE
    cursor cur_all_etf_code is
      select distinct t.code_ from etf_transaction_data t;
    -- 用于根据ETF_CODE获取某一只指数的所有交易记录
    cursor cur_single_etf is
      select *
        from etf_transaction_data t
       where t.code_ = v_etf_code
         and t.date_ between to_date(v_begin_date, 'yyyy-mm-dd') and
             to_date(p_end_date, 'yyyy-mm-dd')
       order by t.date_ asc;
    -- 表示etf_transaction_data表的记录，用于判断120日均线是否单调递减
    cursor cur_120_etf is
      select *
        from (select *
                from etf_transaction_data t
               where t.ma120 is not null
                 and t.code_ = v_etf_code
                 and t.date_ < v_etf_date
               order by t.date_ desc)
       where rownum <= 40;
    -- 表示etf_transaction_data表的记录，用于判断250日均线是否单调递减
    cursor cur_250_etf is
      select *
        from (select *
                from etf_transaction_data t
               where t.ma250 is not null
                 and t.code_ = v_etf_code
                 and t.date_ < v_etf_date
               order by t.date_ desc)
       where rownum <= 40;
  begin
    for i in cur_all_etf_code loop
      v_etf_code                     := i.code_;
      v_init_last_acc_profit_loss    := 100;
      v_start_track_gold_cross_stage := 0;
    
      -- 设置开始时间
      begin
        select to_char(max(t.sell_date) + 1, 'yyyy-mm-dd')
          into v_begin_date
          from mdl_etf_close_price_ma5_g_c t
         where t.etf_code = v_etf_code
           and t.type_ = p_type;
      exception
        when no_data_found then
          dbms_output.put_line('v_etf_code为【' || v_etf_code || '】，
          在mdl_etf_macd_gold_cross表中没有记录');
          v_begin_date := p_default_begin_date;
      end;
      if v_begin_date is null then
        v_begin_date := p_default_begin_date;
      end if;
    
      for j in cur_single_etf loop
        v_etf_date           := j.date_;
        v_record_num         := null;
        v_last_ma120         := null;
        v_last_ma250         := null;
        v_120_250_increasing := 1;
      
        -- 判断120日均线是否单调递减
        if p_validate_120_not_decreasing = 1 then
          select count(*)
            into v_record_num
            from etf_transaction_data t
           where t.ma120 is not null
             and t.code_ = v_etf_code
             and t.date_ <= v_etf_date;
          if v_record_num < 40 then
            continue;
          end if;
          for y in cur_120_etf loop
            if v_last_ma120 is null then
              v_last_ma120 := y.ma120;
              continue;
            end if;
            if v_last_ma120 < y.ma120 then
              v_120_250_increasing := 0;
              exit;
            end if;
            v_last_ma120 := y.ma120;
          end loop;
        end if;
      
        -- 判断250日均线是否单调递减
        if p_validate_250_not_decreasing = 1 then
          select count(*)
            into v_record_num
            from etf_transaction_data t
           where t.ma250 is not null
             and t.code_ = v_etf_code
             and t.date_ <= v_etf_date;
          if v_record_num < 40 then
            continue;
          end if;
          for y in cur_250_etf loop
            if v_last_ma250 is null then
              v_last_ma250 := y.ma250;
              continue;
            end if;
            if v_last_ma250 < y.ma250 then
              v_120_250_increasing := 0;
              exit;
            end if;
            v_last_ma250 := y.ma250;
          end loop;
        end if;
      
        -- 如果120日和250日均线有一个是单调递减，则跳过。但是如果之前已经买入，则不跳过
        if p_validate_120_not_decreasing = 1 or
           p_validate_250_not_decreasing = 1 then
          if v_120_250_increasing = 0 and
             v_start_track_gold_cross_stage = 0 then
            continue;
          end if;
        end if;
      
        if j.close_price > j.ma5 then
          if v_start_track_gold_cross_stage = 0 then
            -- 买入
            v_temp_etf_code                := j.code_;
            v_temp_etf_buy_date            := j.date_;
            v_temp_etf_buy_price           := j.close_price;
            v_temp_etf_buy_ma5             := j.ma5;
            v_start_track_gold_cross_stage := 1;
          else
            continue;
          end if;
        end if;
      
        if j.close_price <= j.ma5 then
          if v_start_track_gold_cross_stage = 1 then
            -- 卖出
            v_temp_etf_sell_date        := j.date_;
            v_temp_etf_sell_price       := j.close_price;
            v_temp_etf_sell_ma5         := j.ma5;
            v_temp_profit_loss          := round((v_temp_etf_sell_price -
                                                 v_temp_etf_buy_price) /
                                                 v_temp_etf_buy_price,
                                                 4) * 100;
            v_init_last_acc_profit_loss := v_init_last_acc_profit_loss *
                                           (1 + v_temp_profit_loss / 100);
            -- 插入记录
            insert into MDL_ETF_CLOSE_PRICE_MA5_G_C
              (buy_date,
               sell_date,
               buy_price,
               sell_price,
               profit_loss,
               etf_code,
               accumulative_profit_loss,
               buy_ma5,
               sell_ma5,
               type_)
            values
              (v_temp_etf_buy_date,
               v_temp_etf_sell_date,
               v_temp_etf_buy_price,
               v_temp_etf_sell_price,
               v_temp_profit_loss,
               v_temp_etf_code,
               v_init_last_acc_profit_loss,
               v_temp_etf_buy_ma5,
               v_temp_etf_sell_ma5,
               p_type);
          
            -- 重置为0，表示还没有买入
            v_start_track_gold_cross_stage := 0;
          else
            continue;
          end if;
        end if;
      end loop;
    end loop;
    commit;
  end CAL_MDL_ETF_CLOSE_PRICE_MA5_GC;

  /*------------------- 海量地向表MDL_ETF_HEI_KIN_ASHI_DOWN_UP中插入数据 ---------------------*/
  procedure CAL_MDL_ETF_H_K_A_DOWN_UP(p_validate_120_not_decreasing in number,
                                      p_validate_250_not_decreasing in number,
                                      p_default_begin_date          in varchar2,
                                      p_end_date                    in varchar2,
                                      p_type                        in number) as
    -- 表示ETF_CODE
    v_etf_code varchar2(100);
    -- 表示开始时间
    v_begin_date varchar2(100);
    -- 表示DATE
    v_etf_date date;
    -- 记录数量
    v_record_num number;
    -- 上一个120日均线
    v_last_ma120 number;
    -- 上一个250日均线
    v_last_ma250 number;
    -- 1表示120日和250日均线都单调递增，0表示120日和250日均线至少有一个是递减的
    v_120_250_increasing number;
    -- 作为临时变量，表示ETF_CODE,BUY_DATE,SELL_DATE,BUY_PRICE,SELL_PRICE
    v_temp_etf_code       varchar2(100);
    v_temp_etf_buy_date   date;
    v_temp_etf_sell_date  date;
    v_temp_etf_buy_price  number;
    v_temp_etf_sell_price number;
    -- 如果为1，则表示已经买入指数；如果为0，则表示还没有买入etf
    v_start_track_h_k_a_stage number;
    -- 每只etf初始的accumulative_profit_loss值为100（表示百分之一百），之后代表上一次交易的累计盈亏百分比
    v_init_last_acc_profit_loss number;
    -- 表示字段PROFIT_LOSS的临时变量
    v_temp_profit_loss number;
    -- 用于获取所有的CODE_
    cursor cur_all_etf_code is
      select distinct t.code_ from etf_transaction_data t;
    -- 用于根据ETF_CODE获取某一只etf的所有交易记录
    cursor cur_single_etf is
      select *
        from etf_transaction_data t
       where t.code_ = v_etf_code
         and t.date_ between to_date(v_begin_date, 'yyyy-mm-dd') and
             to_date(p_end_date, 'yyyy-mm-dd')
       order by t.date_ asc;
    -- 表示etf_transaction_data表的记录，用于判断120日均线是否单调递减
    cursor cur_120_etf is
      select *
        from (select *
                from etf_transaction_data t
               where t.ma120 is not null
                 and t.code_ = v_etf_code
                 and t.date_ < v_etf_date
               order by t.date_ desc)
       where rownum <= 40;
    -- 表示etf_transaction_data表的记录，用于判断250日均线是否单调递减
    cursor cur_250_etf is
      select *
        from (select *
                from etf_transaction_data t
               where t.ma250 is not null
                 and t.code_ = v_etf_code
                 and t.date_ < v_etf_date
               order by t.date_ desc)
       where rownum <= 40;
  begin
    for i in cur_all_etf_code loop
      v_etf_code                  := i.code_;
      v_init_last_acc_profit_loss := 100;
      v_start_track_h_k_a_stage   := 0;
    
      -- 设置开始时间
      begin
        select to_char(max(t.sell_date) + 1, 'yyyy-mm-dd')
          into v_begin_date
          from mdl_etf_hei_kin_ashi_down_up t
         where t.etf_code = v_etf_code
           and t.type_ = p_type;
      exception
        when no_data_found then
          dbms_output.put_line('v_etf_code为【' || v_etf_code || '】，
          在mdl_etf_hei_kin_ashi_down_up表中没有记录');
          v_begin_date := p_default_begin_date;
      end;
      if v_begin_date is null then
        v_begin_date := p_default_begin_date;
      end if;
    
      for j in cur_single_etf loop
        v_etf_date           := j.date_;
        v_record_num         := null;
        v_last_ma120         := null;
        v_last_ma250         := null;
        v_120_250_increasing := 1;
      
        -- 判断120日均线是否单调递减
        if p_validate_120_not_decreasing = 1 then
          select count(*)
            into v_record_num
            from etf_transaction_data t
           where t.ma120 is not null
             and t.code_ = v_etf_code
             and t.date_ <= v_etf_date;
          if v_record_num < 40 then
            continue;
          end if;
          for y in cur_120_etf loop
            if v_last_ma120 is null then
              v_last_ma120 := y.ma120;
              continue;
            end if;
            if v_last_ma120 < y.ma120 then
              v_120_250_increasing := 0;
              exit;
            end if;
            v_last_ma120 := y.ma120;
          end loop;
        end if;
      
        -- 判断250日均线是否单调递减
        if p_validate_250_not_decreasing = 1 then
          select count(*)
            into v_record_num
            from etf_transaction_data t
           where t.ma250 is not null
             and t.code_ = v_etf_code
             and t.date_ <= v_etf_date;
          if v_record_num < 40 then
            continue;
          end if;
          for y in cur_250_etf loop
            if v_last_ma250 is null then
              v_last_ma250 := y.ma250;
              continue;
            end if;
            if v_last_ma250 < y.ma250 then
              v_120_250_increasing := 0;
              exit;
            end if;
            v_last_ma250 := y.ma250;
          end loop;
        end if;
      
        -- 如果120日和250日均线有一个是单调递减，则跳过。但是如果之前已经买入，则不跳过
        if p_validate_120_not_decreasing = 1 or
           p_validate_250_not_decreasing = 1 then
          if v_120_250_increasing = 0 and v_start_track_h_k_a_stage = 0 then
            continue;
          end if;
        end if;
      
        if j.ha_close_price <= j.ha_open_price then
          -- 卖出
          if v_start_track_h_k_a_stage = 1 then
            v_start_track_h_k_a_stage   := 0;
            v_temp_etf_sell_date        := j.date_;
            v_temp_etf_sell_price       := j.close_price;
            v_temp_profit_loss          := round((v_temp_etf_sell_price -
                                                 v_temp_etf_buy_price) /
                                                 v_temp_etf_buy_price,
                                                 4) * 100;
            v_init_last_acc_profit_loss := v_init_last_acc_profit_loss *
                                           (1 + v_temp_profit_loss / 100);
          
            -- 插入记录
            insert into mdl_etf_hei_kin_ashi_down_up
              (etf_code,
               sell_date,
               sell_price,
               buy_date,
               buy_price,
               accumulative_profit_loss,
               profit_loss,
               type_)
            values
              (v_temp_etf_code,
               v_temp_etf_sell_date,
               v_temp_etf_sell_price,
               v_temp_etf_buy_date,
               v_temp_etf_buy_price,
               v_init_last_acc_profit_loss,
               v_temp_profit_loss,
               p_type);
          else
            continue;
          end if;
        end if;
      
        if j.ha_close_price > j.ha_open_price then
          -- 买入
          if v_start_track_h_k_a_stage != 1 then
            v_start_track_h_k_a_stage := 1;
            v_temp_etf_buy_date       := j.date_;
            v_temp_etf_buy_price      := j.close_price;
            v_temp_etf_code           := j.code_;
          end if;
        end if;
      end loop;
    end loop;
    commit;
  end CAL_MDL_ETF_H_K_A_DOWN_UP;

  /*---------------- 海量地向表MDL_ETF_KD_GOLD_CROSS中插入数据 -----------------*/
  procedure CAL_MDL_ETF_KD_GOLD_CROSS(p_validate_120_not_decreasing in number,
                                      p_validate_250_not_decreasing in number,
                                      p_default_begin_date          in varchar2,
                                      p_end_date                    in varchar2,
                                      p_type                        in number) as
    -- 表示ETF_CODE
    v_etf_code varchar2(100);
    -- 表示开始时间
    v_begin_date varchar2(100);
    -- 表示ETF_DATE
    v_etf_date date;
    -- 记录数量
    v_record_num number;
    -- 上一个120日均线
    v_last_ma120 number;
    -- 上一个250日均线
    v_last_ma250 number;
    -- 1表示120日和250日均线都单调递增，0表示120日和250日均线至少有一个是递减的
    v_120_250_increasing number;
    -- 作为临时变量，表示ETF_CODE,BUY_DATE,SELL_DATE,BUY_PRICE,SELL_PRICE,K,D
    v_temp_etf_code       varchar2(100);
    v_temp_etf_buy_date   date;
    v_temp_etf_sell_date  date;
    v_temp_etf_buy_price  number;
    v_temp_etf_sell_price number;
    v_temp_etf_buy_k      number;
    v_temp_etf_sell_k     number;
    v_temp_etf_buy_d      number;
    v_temp_etf_sell_d     number;
    -- 如果为1，则表示已经买入etf了；如果为0，则表示还没有买入etf
    v_start_track_kd_g_c_stage number;
    -- 每只etf初始的accumulative_profit_loss值为100（表示百分之一百），之后代表上一次交易的累计盈亏百分比
    v_init_last_acc_profit_loss number;
    -- 表示字段PROFIT_LOSS的临时变量
    v_temp_profit_loss number;
    -- 用于获取所有的ETF_CODE
    cursor cur_all_etf_code is
      select distinct t.code_ from etf_transaction_data t;
    -- 用于根据ETC_CODE获取某一只etf的所有交易记录
    cursor cur_single_etf is
      select *
        from etf_transaction_data t
       where t.code_ = v_etf_code
         and t.date_ between to_date(v_begin_date, 'yyyy-mm-dd') and
             to_date(p_end_date, 'yyyy-mm-dd')
       order by t.date_ asc;
    -- 表示etf_transaction_data表的记录，用于判断120日均线是否单调递减
    cursor cur_120_etf is
      select *
        from (select *
                from etf_transaction_data t
               where t.ma120 is not null
                 and t.code_ = v_etf_code
                 and t.date_ < v_etf_date
               order by t.date_ desc)
       where rownum <= 40;
    -- 表示etf_transaction_data表的记录，用于判断250日均线是否单调递减
    cursor cur_250_etf is
      select *
        from (select *
                from etf_transaction_data t
               where t.ma250 is not null
                 and t.code_ = v_etf_code
                 and t.date_ < v_etf_date
               order by t.date_ desc)
       where rownum <= 40;
  begin
    for i in cur_all_etf_code loop
      v_etf_code                  := i.code_;
      v_init_last_acc_profit_loss := 100;
      v_start_track_kd_g_c_stage  := 0;
    
      -- 设置开始时间
      begin
        select to_char(max(t.sell_date) + 1, 'yyyy-mm-dd')
          into v_begin_date
          from mdl_etf_kd_gold_cross t
         where t.etf_code = v_etf_code
           and t.type_ = p_type;
      exception
        when no_data_found then
          dbms_output.put_line('v_etf_code为【' || v_etf_code || '】，
          在mdl_etf_kd_gold_cross表中没有记录');
          v_begin_date := p_default_begin_date;
      end;
      if v_begin_date is null then
        v_begin_date := p_default_begin_date;
      end if;
    
      for j in cur_single_etf loop
        v_etf_date           := j.date_;
        v_record_num         := null;
        v_last_ma120         := null;
        v_last_ma250         := null;
        v_120_250_increasing := 1;
      
        -- 判断120日均线是否单调递减
        if p_validate_120_not_decreasing = 1 then
          select count(*)
            into v_record_num
            from etf_transaction_data t
           where t.ma120 is not null
             and t.code_ = v_etf_code
             and t.date_ <= v_etf_date;
          if v_record_num < 40 then
            continue;
          end if;
          for y in cur_120_etf loop
            if v_last_ma120 is null then
              v_last_ma120 := y.ma120;
              continue;
            end if;
            if v_last_ma120 < y.ma120 then
              v_120_250_increasing := 0;
              exit;
            end if;
            v_last_ma120 := y.ma120;
          end loop;
        end if;
      
        -- 判断250日均线是否单调递减
        if p_validate_250_not_decreasing = 1 then
          select count(*)
            into v_record_num
            from etf_transaction_data t
           where t.ma250 is not null
             and t.code_ = v_etf_code
             and t.date_ <= v_etf_date;
          if v_record_num < 40 then
            continue;
          end if;
          for y in cur_250_etf loop
            if v_last_ma250 is null then
              v_last_ma250 := y.ma250;
              continue;
            end if;
            if v_last_ma250 < y.ma250 then
              v_120_250_increasing := 0;
              exit;
            end if;
            v_last_ma250 := y.ma250;
          end loop;
        end if;
      
        -- 如果120日和250日均线有一个是单调递减，则跳过。但是如果之前已经买入，则不跳过
        if p_validate_120_not_decreasing = 1 or
           p_validate_250_not_decreasing = 1 then
          if v_120_250_increasing = 0 and v_start_track_kd_g_c_stage = 0 then
            continue;
          end if;
        end if;
      
        if j.k <= j.d then
          -- 卖出
          if v_start_track_kd_g_c_stage = 1 then
            v_start_track_kd_g_c_stage  := 0;
            v_temp_etf_sell_date        := j.date_;
            v_temp_etf_sell_price       := j.close_price;
            v_temp_etf_sell_k           := j.k;
            v_temp_etf_sell_d           := j.d;
            v_temp_profit_loss          := round((v_temp_etf_sell_price -
                                                 v_temp_etf_buy_price) /
                                                 v_temp_etf_buy_price,
                                                 4) * 100;
            v_init_last_acc_profit_loss := v_init_last_acc_profit_loss *
                                           (1 + v_temp_profit_loss / 100);
          
            -- 插入记录
            insert into mdl_etf_kd_gold_cross
              (etf_code,
               sell_date,
               sell_price,
               sell_k,
               sell_d,
               buy_date,
               buy_price,
               buy_k,
               buy_d,
               accumulative_profit_loss,
               profit_loss,
               type_)
            values
              (v_temp_etf_code,
               v_temp_etf_sell_date,
               v_temp_etf_sell_price,
               v_temp_etf_sell_k,
               v_temp_etf_sell_d,
               v_temp_etf_buy_date,
               v_temp_etf_buy_price,
               v_temp_etf_buy_k,
               v_temp_etf_buy_d,
               v_init_last_acc_profit_loss,
               v_temp_profit_loss,
               p_type);
          else
            continue;
          end if;
        end if;
      
        if j.k > j.d then
          -- 买入
          if v_start_track_kd_g_c_stage != 1 then
            v_start_track_kd_g_c_stage := 1;
            v_temp_etf_buy_date        := j.date_;
            v_temp_etf_buy_price       := j.close_price;
            v_temp_etf_buy_k           := j.k;
            v_temp_etf_buy_d           := j.d;
            v_temp_etf_code            := j.code_;
          end if;
        end if;
      end loop;
    end loop;
    commit;
  end CAL_MDL_ETF_KD_GOLD_CROSS;

  /*------------------- 海量地向表MDL_ETF_BULL_SHORT_LINE_UP中插入数据 --------------------*/
  procedure CAL_MDL_ETF_B_S_LINE_UP as
    -- 表示code_
    v_etf_code varchar2(100);
    -- 判断哪根均线作为牛熊线时，乖离率的阈值
    v_bias_top_threshold    number := 10;
    v_bias_bottom_threshold number := -15;
    -- 当前交易日期的牛熊线
    v_cur_bull_short_line varchar2(11);
    -- 当前交易日期的牛熊线的收盘价
    v_cur_bull_short_line_price number;
    -- 前一个交易日期的牛熊线
    v_last_bull_short_line varchar2(11);
    -- 前一个交易日期的牛熊线的收盘价
    v_last_bull_short_line_price number;
    -- 当前记录
    row_current_etd etf_transaction_data%rowtype;
    -- 前一条记录
    row_last_etd etf_transaction_data%rowtype;
    -- 是否是某只ETF的第一条记录，1表示是，-1表示否
    v_is_first_row number := 1;
    -- 表示是否出现了金叉，1表示是，-1表示否
    v_is_gold_cross number := -1;
    -- 表示是否出现了死叉，1表示是，-1表示否
    v_is_dead_cross number := -1;
    -- 买入价格、买入日期、卖出价格、卖出日期
    v_buy_price  number;
    v_buy_date   date;
    v_sell_price number;
    v_sell_date  date;
    -- 买入时牛熊线和牛熊线价格，卖出时牛熊线和牛熊线价格
    v_b_s_l_when_buy        varchar2(11);
    v_b_s_l_price_when_buy  number;
    v_b_s_l_when_sell       varchar2(11);
    v_b_s_l_price_when_sell number;
    -- 收益率
    v_profit_loss number;
    -- 累计收益率
    v_init_last_acc_profit_loss number;
    -- 所有ETF的etf_code
    cursor cur_etf_code is
      select distinct t.code_ from etf_transaction_data t;
    --where t.code_ = '600971';
    -- 某一只ETF的全部交易记录，按升序排列，ma250和bias250不能为空
    cursor cur_etf_transaction_data is
      select *
        from etf_transaction_data t
       where t.code_ = v_etf_code
      --and t.date_ >= to_date('2008-1-30', 'yyyy-mm-dd')
       order by t.date_ asc;
  begin
    for i in cur_etf_code loop
      v_etf_code := i.code_;
    
      -- 重置
      v_is_first_row              := 1;
      v_init_last_acc_profit_loss := 100;
    
      for j in cur_etf_transaction_data loop
      
        -- 如果是第一条记录，则跳过
        if v_is_first_row = 1 then
          v_is_first_row := -1;
          row_last_etd   := j;
          continue;
        else
          row_current_etd := j;
        end if;
      
        -- 判断前一个交易日期的牛熊线
        if row_last_etd.bias250 <= v_bias_top_threshold and
           row_last_etd.bias250 >= v_bias_bottom_threshold then
          v_last_bull_short_line       := 'ma250';
          v_last_bull_short_line_price := row_last_etd.ma250;
        elsif row_last_etd.bias120 <= v_bias_top_threshold and
              row_last_etd.bias120 >= v_bias_bottom_threshold then
          v_last_bull_short_line       := 'ma120';
          v_last_bull_short_line_price := row_last_etd.ma120;
        elsif row_last_etd.bias60 <= v_bias_top_threshold and
              row_last_etd.bias60 >= v_bias_bottom_threshold then
          v_last_bull_short_line       := 'ma60';
          v_last_bull_short_line_price := row_last_etd.ma60;
        elsif row_last_etd.bias20 <= v_bias_top_threshold and
              row_last_etd.bias20 >= v_bias_bottom_threshold then
          v_last_bull_short_line       := 'ma20';
          v_last_bull_short_line_price := row_last_etd.ma20;
        elsif row_last_etd.bias10 <= v_bias_top_threshold and
              row_last_etd.bias10 >= v_bias_bottom_threshold then
          v_last_bull_short_line       := 'ma10';
          v_last_bull_short_line_price := row_last_etd.ma10;
        elsif row_last_etd.bias5 <= v_bias_top_threshold and
              row_last_etd.bias5 >= v_bias_bottom_threshold then
          v_last_bull_short_line       := 'ma5';
          v_last_bull_short_line_price := row_last_etd.ma5;
        else
          v_last_bull_short_line       := 'ma2';
          v_last_bull_short_line_price := row_last_etd.last_close_price;
        end if;
      
        -- 判断当前交易日期的牛熊线
        if row_current_etd.bias250 <= v_bias_top_threshold and
           row_current_etd.bias250 >= v_bias_bottom_threshold then
          v_cur_bull_short_line       := 'ma250';
          v_cur_bull_short_line_price := row_current_etd.ma250;
        elsif row_current_etd.bias120 <= v_bias_top_threshold and
              row_current_etd.bias120 >= v_bias_bottom_threshold then
          v_cur_bull_short_line       := 'ma120';
          v_cur_bull_short_line_price := row_current_etd.ma120;
        elsif row_current_etd.bias60 <= v_bias_top_threshold and
              row_current_etd.bias60 >= v_bias_bottom_threshold then
          v_cur_bull_short_line       := 'ma60';
          v_cur_bull_short_line_price := row_current_etd.ma60;
        elsif row_current_etd.bias20 <= v_bias_top_threshold and
              row_current_etd.bias20 >= v_bias_bottom_threshold then
          v_cur_bull_short_line       := 'ma20';
          v_cur_bull_short_line_price := row_current_etd.ma20;
        elsif row_current_etd.bias10 <= v_bias_top_threshold and
              row_current_etd.bias10 >= v_bias_bottom_threshold then
          v_cur_bull_short_line       := 'ma10';
          v_cur_bull_short_line_price := row_current_etd.ma10;
        elsif row_current_etd.bias5 <= v_bias_top_threshold and
              row_current_etd.bias5 >= v_bias_bottom_threshold then
          v_cur_bull_short_line       := 'ma5';
          v_cur_bull_short_line_price := row_current_etd.ma5;
        else
          v_cur_bull_short_line       := 'ma2';
          v_cur_bull_short_line_price := row_current_etd.last_close_price;
        end if;
      
        -- 在金叉还没出现的情况下，前一个交易日，收盘价是否在牛熊线之下，当前交易日，收盘价是否在牛熊线之上
        if v_is_gold_cross = -1 and
           row_last_etd.close_price < v_last_bull_short_line_price and
           row_current_etd.close_price >= v_cur_bull_short_line_price then
          v_is_gold_cross        := 1;
          v_buy_price            := row_current_etd.close_price;
          v_buy_date             := row_current_etd.date_;
          v_b_s_l_when_buy       := v_cur_bull_short_line;
          v_b_s_l_price_when_buy := v_cur_bull_short_line_price;
        end if;
      
        -- 必须在金叉已经出现的情况下，才判断当前交易日，收盘价是否在牛熊线之上，当前交易日，收盘价是否在牛熊线之下
        if v_is_gold_cross = 1 and v_is_dead_cross = -1 and
           row_last_etd.close_price >= v_last_bull_short_line_price and
           row_current_etd.close_price < v_cur_bull_short_line_price then
          v_is_dead_cross         := 1;
          v_sell_price            := row_current_etd.close_price;
          v_sell_date             := row_current_etd.date_;
          v_b_s_l_when_sell       := v_cur_bull_short_line;
          v_b_s_l_price_when_sell := v_cur_bull_short_line_price;
        end if;
      
        -- 插入记录
        if v_is_gold_cross = 1 and v_is_dead_cross = 1 then
          v_profit_loss               := (v_sell_price - v_buy_price) /
                                         v_buy_price * 100;
          v_init_last_acc_profit_loss := v_init_last_acc_profit_loss *
                                         (1 + v_profit_loss / 100);
          insert into mdl_etf_bull_short_line_up
            (etf_code,
             buy_date,
             buy_price,
             sell_date,
             sell_price,
             b_s_l_when_buy,
             b_s_l_price_when_buy,
             b_s_l_when_sell,
             b_s_l_price_when_sell,
             profit_loss,
             accumulative_profit_loss)
          values
            (row_current_etd.code_,
             v_buy_date,
             v_buy_price,
             v_sell_date,
             v_sell_price,
             v_b_s_l_when_buy,
             v_b_s_l_price_when_buy,
             v_b_s_l_when_sell,
             v_b_s_l_price_when_sell,
             v_profit_loss,
             v_init_last_acc_profit_loss);
        
          -- 重置
          v_is_gold_cross := -1;
          v_is_dead_cross := -1;
        end if;
      
        -- 将当前记录赋值给前一条记录
        row_last_etd := row_current_etd;
      end loop;
    
    end loop;
    commit;
  end CAL_MDL_ETF_B_S_LINE_UP;

  /*------------------- 增量地向表MDL_ETF_BULL_SHORT_LINE_UP中插入数据 --------------------*/
  procedure CAL_MDL_ETF_B_S_LINE_UP_INCR(p_date in varchar2) as
    -- 表示CODE_
    v_etf_code varchar2(100);
    -- 表示某只ETF的最大卖出日期
    v_max_sell_date date;
    -- 判断哪根均线作为牛熊线时，乖离率的阈值
    v_bias_top_threshold    number := 10;
    v_bias_bottom_threshold number := -15;
    -- 表示出现金叉之前的一个交易日
    v_gold_cross_previous_etd etf_transaction_data%rowtype;
    -- 表示出现金叉的交易日
    v_gold_cross_current_etd etf_transaction_data%rowtype;
    -- 表示出现死叉之前的一个交易日
    v_dead_cross_previous_etd etf_transaction_data%rowtype;
    -- 表示出现死叉的交易日
    v_dead_cross_current_etd etf_transaction_data%rowtype;
    -- 金叉之前的牛熊线
    v_g_c_previous_b_s_line number;
    -- 金叉时的牛熊线
    v_g_c_current_b_s_line number;
    -- 死叉之前的牛熊线
    --v_d_c_previous_b_s_line number;
    -- 死叉时的牛熊线
    --v_d_c_current_b_s_line number;
    -- 金叉是否已经出现，1表示出现，-1表示未出现
    v_gold_cross number := -1;
    -- 死叉是否已经出现，1表示出现，-1表示未出现
    v_dead_cross number := -1;
    -- 买入价格、买入日期、卖出价格、卖出日期
    v_buy_price  number;
    v_buy_date   date;
    v_sell_price number;
    v_sell_date  date;
    -- 买入时牛熊线和牛熊线价格，卖出时牛熊线和牛熊线价格
    v_b_s_l_when_buy        varchar2(11);
    v_b_s_l_price_when_buy  number;
    v_b_s_l_when_sell       varchar2(11);
    v_b_s_l_price_when_sell number;
    v_temp_b_s_l            varchar2(11);
    --v_temp_b_s_l_price      number;
    -- 收益率
    v_profit_loss number;
    -- 累计收益率
    v_init_last_acc_profit_loss number;
    -- 所有ETF的etf_code
    cursor cur_etf_code is
      select distinct t.code_ from etf_transaction_data t;
    -- 某只ETF，在上次交易日期后的记录，按日期升序排列
    cursor cur_later_transaction_etd is
      select *
        from etf_transaction_data t
       where t.code_ = v_etf_code
         and t.date_ > v_max_sell_date
         and t.date_ <= to_date(p_date, 'yyyy-mm-dd')
       order by t.date_ asc;
  begin
    for i in cur_etf_code loop
      v_etf_code := i.code_;
      
      -- 重置
      v_init_last_acc_profit_loss := 100;
    
      -- 某只ETF的最大卖出日期
      begin
        select max(t.sell_date)
          into v_max_sell_date
          from mdl_etf_bull_short_line_up t
         where t.etf_code = v_etf_code;
      exception
        when no_data_found then
          dbms_output.put_line('etf_code为【' || v_etf_code || '】，
                                                            在MDL_ETF_BULL_SHORT_LINE_UP表中没有最大的卖出日期');
          continue;
      end;
    
      -- 重置
      v_gold_cross_previous_etd := null;
      v_gold_cross_current_etd  := null;
      v_dead_cross_previous_etd := null;
      v_dead_cross_current_etd  := null;
      v_gold_cross              := -1;
      v_dead_cross              := -1;
    
      for j in cur_later_transaction_etd loop
        -- 如果是第一条记录
        if v_gold_cross_previous_etd.code_ is null then
          v_gold_cross_previous_etd := j;
          continue;
        end if;
      
        -- 判断前一天的牛熊线
        if v_gold_cross_previous_etd.bias250 < v_bias_top_threshold and
           v_bias_bottom_threshold < v_gold_cross_previous_etd.bias250 then
          v_g_c_previous_b_s_line := v_gold_cross_previous_etd.ma250;
        elsif v_gold_cross_previous_etd.bias120 < v_bias_top_threshold and
              v_bias_bottom_threshold < v_gold_cross_previous_etd.bias120 then
          v_g_c_previous_b_s_line := v_gold_cross_previous_etd.ma120;
        elsif v_gold_cross_previous_etd.bias60 < v_bias_top_threshold and
              v_bias_bottom_threshold < v_gold_cross_previous_etd.bias60 then
          v_g_c_previous_b_s_line := v_gold_cross_previous_etd.ma60;
        elsif v_gold_cross_previous_etd.bias20 < v_bias_top_threshold and
              v_bias_bottom_threshold < v_gold_cross_previous_etd.bias20 then
          v_g_c_previous_b_s_line := v_gold_cross_previous_etd.ma20;
        elsif v_gold_cross_previous_etd.bias10 < v_bias_top_threshold and
              v_bias_bottom_threshold < v_gold_cross_previous_etd.bias10 then
          v_g_c_previous_b_s_line := v_gold_cross_previous_etd.ma10;
        elsif v_gold_cross_previous_etd.bias5 < v_bias_top_threshold and
              v_bias_bottom_threshold < v_gold_cross_previous_etd.bias5 then
          v_g_c_previous_b_s_line := v_gold_cross_previous_etd.ma5;
        else
          v_g_c_previous_b_s_line := v_gold_cross_previous_etd.close_price;
        end if;
      
        -- 判断当前的牛熊线
        if j.bias250 < v_bias_top_threshold and
           v_bias_bottom_threshold < j.bias250 then
          v_g_c_current_b_s_line := j.ma250;
          v_temp_b_s_l           := 'ma250';
        elsif j.bias120 < v_bias_top_threshold and
              v_bias_bottom_threshold < j.bias120 then
          v_g_c_current_b_s_line := j.ma120;
          v_temp_b_s_l           := 'ma120';
        elsif j.bias60 < v_bias_top_threshold and
              v_bias_bottom_threshold < j.bias60 then
          v_g_c_current_b_s_line := j.ma60;
          v_temp_b_s_l           := 'm60';
        elsif j.bias20 < v_bias_top_threshold and
              v_bias_bottom_threshold < j.bias20 then
          v_g_c_current_b_s_line := j.ma20;
          v_temp_b_s_l           := 'ma20';
        elsif j.bias10 < v_bias_top_threshold and
              v_bias_bottom_threshold < j.bias10 then
          v_g_c_current_b_s_line := j.ma10;
          v_temp_b_s_l           := 'ma10';
        elsif j.bias5 < v_bias_top_threshold and
              v_bias_bottom_threshold < j.bias5 then
          v_g_c_current_b_s_line := j.ma5;
          v_temp_b_s_l           := 'ma5';
        else
          v_g_c_current_b_s_line := j.last_close_price;
          v_temp_b_s_l           := 'ma2';
        end if;
      
        -- 判断金叉是否出现
        if v_gold_cross = -1 and v_dead_cross = -1 then
          if v_gold_cross_previous_etd.close_price <
             v_g_c_previous_b_s_line and
             j.close_price >= v_g_c_current_b_s_line then
            v_gold_cross           := 1;
            v_buy_price            := j.close_price;
            v_buy_date             := j.date_;
            v_b_s_l_when_buy       := v_temp_b_s_l;
            v_b_s_l_price_when_buy := v_g_c_current_b_s_line;
          end if;
        end if;
      
        -- 判断金叉、死叉是否出现
        if v_gold_cross = 1 and v_dead_cross = -1 then
          if v_gold_cross_previous_etd.close_price >=
             v_g_c_previous_b_s_line and
             j.close_price < v_g_c_current_b_s_line then
            v_dead_cross            := 1;
            v_sell_price            := j.close_price;
            v_sell_date             := j.date_;
            v_b_s_l_when_sell       := v_temp_b_s_l;
            v_b_s_l_price_when_sell := v_g_c_current_b_s_line;
          
            v_profit_loss               := (v_sell_price - v_buy_price) /
                                           v_buy_price * 100;
            v_init_last_acc_profit_loss := v_init_last_acc_profit_loss *
                                           (1 + v_profit_loss / 100);
            -- 插入记录
            insert into mdl_etf_bull_short_line_up
              (etf_code,
               buy_date,
               buy_price,
               sell_date,
               sell_price,
               b_s_l_when_buy,
               b_s_l_price_when_buy,
               b_s_l_when_sell,
               b_s_l_price_when_sell,
               profit_loss,
               accumulative_profit_loss)
            values
              (j.code_,
               v_buy_date,
               v_buy_price,
               v_sell_date,
               v_sell_price,
               v_b_s_l_when_buy,
               v_b_s_l_price_when_buy,
               v_b_s_l_when_sell,
               v_b_s_l_price_when_sell,
               v_profit_loss,
               v_init_last_acc_profit_loss);
          
            -- 重置
            v_gold_cross := 1;
            v_dead_cross := 1;
          
          end if;
        end if;
      
        v_gold_cross_previous_etd := j;
      
      end loop;
    end loop;
    commit;
  end CAL_MDL_ETF_B_S_LINE_UP_INCR;

end PKG_MODEL_ETF;